﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Xml;
using DiscoveryLogic.Common.Utilities;

namespace DiscoveryLogic.Analytics.DataObjects
{
    public class EntityDataSet
    {
        private string _DataSetName;
        /// <summary></summary>
        public string DataSetName
        {
            get
            {
                return this._DataSetName;
            }
            set
            {
                this._DataSetName = value;
            }
        }

        private List<EntityBase> _Entities;
        /// <summary></summary>
        public List<EntityBase> Entities
        {
            get
            {
                return this._Entities;
            }
            set
            {
                this._Entities = value;
            }
        }

        private EntityType _EntityType;
        /// <summary></summary>
        public Common.Utilities.EntityType EntityType
        {
            get
            {
                return this._EntityType;
            }
            set
            {
                this._EntityType = value;
            }
        }

        private SetDataSourceType _SourceType;
        /// <summary></summary>
        public SetDataSourceType SourceType
        {
            get
            {
                return this._SourceType;
            }
            set
            {
                this._SourceType = value;
            }
        }

        private string _IconPath;
        /// <summary></summary>
        public string IconPath
        {
            get
            {
                return this._IconPath;
            }
            set
            {
                this._IconPath = value;
            }
        }

        public EntityDataSet(string setName, string iconPath)
        {
            this._DataSetName = setName;
            this._IconPath = iconPath;
            this._EntityType = EntityType.Grants;
            this._Entities=new List<EntityBase>();
            this._SourceType = SetDataSourceType.DB;
        }

        public EntityDataSet(string setName, string iconPath,
            EntityType entityType, SetDataSourceType srcType, 
            List<EntityBase> entities)
            :this(setName, iconPath)
        {
            this._EntityType = entityType;
            this._Entities = entities;
            this._SourceType = srcType;
        }

        public void Save()
        {
            string appFolderPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
            appFolderPath = Path.Combine(appFolderPath, "Network Data");
            if (!Directory.Exists(appFolderPath))
                Directory.CreateDirectory(appFolderPath);
            string extension = EntityTypeUtil.GetEntityDataSetFileExtension(this.EntityType);
            
            string filePath = Path.Combine(appFolderPath, this.DataSetName + extension);
            if(File.Exists(filePath))
                File.Delete(filePath);

            XmlDocument xDoc = new XmlDocument();
            xDoc.LoadXml("<DataSet></DataSet>");
            XmlNode root = xDoc.DocumentElement;
            XmlDataUtil.UpdateAttribute(ref xDoc, root,"DataSetName",this.DataSetName);
            XmlDataUtil.UpdateAttribute(ref xDoc, root, "IconPath", this.IconPath);
            XmlDataUtil.UpdateAttribute(ref xDoc, root, "EntityType", this.EntityType.ToString());
            XmlDataUtil.UpdateAttribute(ref xDoc, root, "SrcType", this.SourceType.ToString());
            XmlNode entityNodes = XmlDataUtil.AddElement(ref xDoc, root, "Entities");
            if(this.Entities !=null && this.Entities.Count>0)
            {
                foreach(EntityBase entity in this.Entities)
                {
                    XmlNode entityNode = XmlDataUtil.AddElement(ref xDoc, entityNodes, "Entity");
                    entity.Save(ref xDoc, entityNode);
                }
            }
            xDoc.Save(filePath);
        }

        public static EntityDataSet Read(XmlDocument xDoc)
        {
            EntityDataSet dataSet = new EntityDataSet(string.Empty, string.Empty);
            XmlNode root = xDoc.DocumentElement;
            dataSet.DataSetName = XmlDataUtil.GetAttributeValue(root, "DataSetName", "");
            dataSet.IconPath = XmlDataUtil.GetAttributeValue(root, "IconPath", "");
            dataSet.EntityType =
                (Common.Utilities.EntityType)
                Enum.Parse(typeof (EntityType),
                           XmlDataUtil.GetAttributeValue(root, "EntityType",
                                                         EntityType.Grants.ToString()));
            dataSet.SourceType =
                (SetDataSourceType)
                Enum.Parse(typeof (SetDataSourceType),
                           XmlDataUtil.GetAttributeValue(root, "SrcType", SetDataSourceType.DB.ToString()));
            dataSet.Entities=new List<EntityBase>();
            XmlNodeList entityNodes = root.SelectNodes("Entities/Entity");
            if(entityNodes !=null && entityNodes.Count>0)
            {
                switch(dataSet.EntityType)
                {
                    case EntityType.Grants:
                        foreach (XmlNode entityNode in entityNodes)
                            dataSet.Entities.Add(GrantDO.Read(entityNode));
                        break;
                    case EntityType.Organizations:
                        foreach (XmlNode entityNode in entityNodes)
                            dataSet.Entities.Add(ExternalOrgDO.Read(entityNode));
                        break;
                    case EntityType.Persons:
                        foreach (XmlNode entityNode in entityNodes)
                            dataSet.Entities.Add(PersonDO.Read(entityNode));
                        break;
                    case EntityType.Publications:
                        foreach (XmlNode entityNode in entityNodes)
                            dataSet.Entities.Add(PublicationDO.Read(entityNode));
                        break;
                    case EntityType.Document:
                        foreach(XmlNode entityNode in entityNodes)
                            dataSet.Entities.Add(Document.Read(entityNode));
                        break;
                    case EntityType.Subject:
                        foreach (XmlNode entityNode in entityNodes)
                            dataSet.Entities.Add(Subject.Read(entityNode));
                        break;
                }
            }
            return dataSet;
        }
    }
}
